﻿#include "stdafx.cuh"
#include "EPSPlot.h"
#include "cuPrintfMain.cuh"
#include "SweepCircleVoronoi.cu"
#include "EventQueue.cu"
#include "VoronoiFunction.cu"

#ifndef _DELETE_IT_
#include "stdafx.h"
#include "SweepCircleVoronoi.h"
#include "EventQueue.h"
#include "VoronoiFunction.h"
#endif


//graphics functions
void SetPosition();
void display();
void init();
void DrawMyself();
bool inBox(const float2& p , const float2& box1 , const float2& box2);
float2 intersectSegBox(const float2& p1 , const float2& p2 , const float2& box1 ,const float2& box2 );


void SetPosition()
{
	glPolygonMode(GL_BACK,GL_LINE);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f,0.0f,-1.5f);
	glTranslatef(0.0f,0.0f,1.5f);
	glScalef(2.0f,2.0f,2.0f);
}



void display()
{
     /*clear window */
	glClearColor(1,1,1,1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    /*draw unit square polygon*/
	SetPosition();
	voronoi_kernel_c();
	DrawMyself();

	glutSwapBuffers();
	//system("pause");
	Sleep(sleepTime);	
}

void ReSize(int cx,int cy)
{    
	glViewport(0,0,cx,cy);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	double scale = 1.5;
	if(cx>cy){
		MinPoint.x = -float(cx)/float(cy)*scale;
		MaxPoint.x = -MinPoint.x;
		MinPoint.y = -scale;
		MaxPoint.y = scale;
		glOrtho(MinPoint.x,MaxPoint.x,MinPoint.y,MaxPoint.y,-10000,10000);
	}else{
		MinPoint.x=-scale;
		MaxPoint.x=scale;
		MinPoint.y=-float(cy)/float(cx)*scale;
		MaxPoint.y=-MinPoint.y;
		glOrtho(MinPoint.x,MaxPoint.x,MinPoint.y,MaxPoint.y,-10000,10000);
	}
	printf( "minx %f miny %f maxx %f  maxy %f " , MinPoint.x , MinPoint.y , MaxPoint.x , MaxPoint.y );
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}




void DrawMyself()
{
	glPushAttrib(GL_ENABLE_BIT|GL_POLYGON_BIT|GL_LINE_BIT);
	glDisable(GL_LIGHTING);

	//printf("h_sites draw %d\n" , h_sitesLength[0]);
	//printf("sites %d",sites.size());
	static int picCount = 0;
	char fileName[100];
	sprintf(fileName,"pic/voronoi-%04d.eps",picCount++);
	EPSPlot plot(fileName,picCorner1.x,picCorner1.y,picCorner2.x,picCorner2.y,picDrawLength,totalLength);
		
	float pointSize = 2;
	float lineWidth = 0.5;
	glPointSize(3);
	glLineWidth(1.5);

	for(int i = 0; i < blockNum * threadNum;++i){
		float2 box1;
		float2 box2;
		box1 = bounds.atHost(i,0);
		box2 = bounds.atHost(i,1);
		Heap <Event>tmpEventHeap;
		tmpEventHeap.initial(&(eventHeaps.atHost(i,0)),(eventHeaps.hostLength())[i],EVENT_HEAP_SIZE);
		float tmpDistance =  tmpEventHeap.top().distance;
		Event nextEvt = GetNextEvent(tmpEventHeap);
		float keyDis = nextEvt.distance;

		glBegin(GL_POINTS);
		{
			plot.setPointSize(pointSize);
			for(int j = 0; j < sites.length(i);++j){
				float2 tmpSite = sites.atHost(i,j);
				//if( !inBox(tmpSite,bounds.atHost(i,0),bounds.atHost(i,1))) continue;
				//printf("print threadnum %d j %d\n" , i , j );
				if(calcDistance(tmpSite,centers.atHost(i,0)) < WXN_EPSILON * tmpDisFromCenterScale ){
					glColor3f(.7f,0.0f,0.5f);
					plot.setRGBColor(.7f,0.0f,0.5f);
				}
				else{
					glColor3f(.7f,0.7f,0.5f);
					plot.setRGBColor(.7f,0.7f,0.5f);
				}
				glVertex2d(tmpSite.x,tmpSite.y);
				plot.drawPointAndChange(tmpSite);
				//printf("tmpSite.x %f tmpSie.y %f\n",tmpSite.x,tmpSite.y);
			}
		}
		glEnd();
		{
			glColor3f(0, 1, 0);
			plot.setRGBColor(0, 1, 0);
			glBegin(GL_POINTS);
			plot.setPointSize(pointSize);
			glVertex2f((float)centers.atHost(i,0).x, (float)centers.atHost(i,0).y);
			plot.drawPointAndChange(centers.atHost(i,0));
			glEnd();
		}

		glColor3f(0,0,0);
		plot.setRGBColor(0,0,0);
		glBegin(GL_LINES);
		{
			plot.setLineWidth(lineWidth);
			plot.setLineCap(0);
			for(int j = 0; j < edges.length(i);++j){
				int2 edge = edges.atHost(i,j);
				float2 p1 = vertices.atHost(i,edge.x);
				float2 p2 = vertices.atHost(i,edge.y);


				if(!displayOutsideFlag){
					if(getIntersectDisplay(p1,p2,box1,box2)){
						glVertex2f(p1.x,p1.y);
						glVertex2f(p2.x,p2.y);
						plot.drawLineAndChange(p1,p2);
					}
				}else{
					glVertex2f(p1.x,p1.y);
					glVertex2f(p2.x,p2.y);
					plot.drawLineAndChange(p1,p2);
				}
			}
		}
		glEnd();
		glColor3f(1,0,0);
		plot.setRGBColor(1,0,0);
		plot.setLineWidth(lineWidth);
		glBegin(GL_LINE_STRIP);
		{
			glVertex2f(bounds.atHost(i,0).x,bounds.atHost(i,0).y);
			glVertex2f(bounds.atHost(i,1).x,bounds.atHost(i,0).y);
			glVertex2f(bounds.atHost(i,1).x,bounds.atHost(i,1).y);
			glVertex2f(bounds.atHost(i,0).x,bounds.atHost(i,1).y);
			glVertex2f(bounds.atHost(i,0).x,bounds.atHost(i,0).y);
			plot.drawLineAndChange(bounds.atHost(i,0).x,bounds.atHost(i,0).y,bounds.atHost(i,1).x,bounds.atHost(i,0).y);
			plot.drawLineAndChange(bounds.atHost(i,1).x,bounds.atHost(i,0).y,bounds.atHost(i,1).x,bounds.atHost(i,1).y);
			plot.drawLineAndChange(bounds.atHost(i,1).x,bounds.atHost(i,1).y,bounds.atHost(i,0).x,bounds.atHost(i,1).y);
			plot.drawLineAndChange(bounds.atHost(i,0).x,bounds.atHost(i,1).y,bounds.atHost(i,0).x,bounds.atHost(i,0).y);
		}
		glEnd();

		//wavefront circle
		glColor3f(0, 1, 0);
		plot.setRGBColor(0,1,0);
		plot.setLineWidth(lineWidth);
		glBegin(GL_LINES);
		for (int j = 0; j < 360; ++j)
		{		
			double angle1  = 2 * M_PI / 360 * (j % 360);
			double angle2  = 2 * M_PI / 360 * ((j+1) % 360);
			float2 p1 = make_float2((float)(centers.atHost(i,0).x + tmpDistance * cos(angle1)), (float)(centers.atHost(i,0).y + tmpDistance * sin(angle1)));
			float2 p2 = make_float2((float)(centers.atHost(i,0).x + tmpDistance * cos(angle2)), (float)(centers.atHost(i,0).y + tmpDistance * sin(angle2)));
			
			if(!displayOutsideFlag){
				if(getIntersectDisplay(p1,p2,box1,box2)){
					glVertex2f(p1.x,p1.y);
					glVertex2f(p2.x,p2.y);
					plot.drawLineAndChange(p1,p2);
				}
			}else{
				glVertex2f(p1.x,p1.y);
				glVertex2f(p2.x,p2.y);
				plot.drawLineAndChange(p1,p2);
			}
		}
		glEnd();

		//Active edges;
		
		glColor3f(0, 1, 1);
		plot.setRGBColor(0,1,1);
		plot.setLineWidth(lineWidth);
		glBegin(GL_LINES);
		{
			EllipseArc* headArc;
			ActiveEdge* edge = NULL;
			EllipseArc* nextActiveArc = NULL;
			if (keyDis < FLT_MAX && nextEvt.type == EllipseVanish)
			{
				nextActiveArc = nextEvt.arc;
				//printf("bingo\n");
			}
			//printf("head arc %d \n" , headArcsPos.atHost(i,0));
			if ( headArcsPos.atHost(i,0) != -1){
				headArc = &(arcs.atHost(i,headArcsPos.atHost(i,0)));
				edge = headArc->leftActiveEdge;
			}else{
				headArc = NULL;
			}
			do
			{
				if (edge != NULL)
				{
					if (nextActiveArc != NULL && (nextActiveArc->leftActiveEdge == edge || nextActiveArc->rightActiveEdge == edge))
					{
						glColor3f(1, 0, 0);
						plot.setRGBColor(1,0,0);
					}
					else
					{
						glColor3f(0, 1, 1);
						plot.setRGBColor(0,1,1);
					}
					float2 p1 = make_float2(vertices.atHost(i,edge->fixedVertex).x,vertices.atHost(i,edge->fixedVertex).y);
					//glVertex2f((float)vertexPool.at(edge->fixedVertex).x, (float)vertexPool.at(edge->fixedVertex).y);
					float2 p2 = edge->GetCurrentPos(tmpDistance);
					if(!displayOutsideFlag){
						if(getIntersectDisplay(p1,p2,box1,box2)){
							glVertex2f(p1.x,p1.y);
							glVertex2f(p2.x,p2.y);
							plot.drawLineAndChange(p1,p2);
						}

					}else{
						glVertex2f(p1.x,p1.y);
						glVertex2f(p2.x,p2.y);
						plot.drawLineAndChange(p1,p2);
					}

					if (edge->leftArc == NULL)
						edge = NULL;
					else
						edge = edge->leftArc->leftActiveEdge;
				}
			}
			while (edge != NULL && edge != headArc->leftActiveEdge);
		}
		glEnd();
		
		
		
		//arcs
		{
			EllipseArc* headArc;
			if ( headArcsPos.atHost(i,0) != -1){
				headArc = &(arcs.atHost(i,headArcsPos.atHost(i,0)));
			}else{
				headArc = NULL;
			}

			//printf("tmpDistance ?? %f\n" , tmpDistance );


			EllipseArc* arc = headArc;
			EllipseArc* nextActiveArc = NULL;
			if (keyDis < FLT_MAX && nextEvt.type == EllipseVanish)
			{
				nextActiveArc = nextEvt.arc;
			}
			int nArcNum = 0;
			int cnt = 0;
			float2 box1;
			float2 box2;
			box1 = bounds.atHost(i,0);
			box2 = bounds.atHost(i,1);

			do
			{
				//printf("what the fuck cnt %d??\n" , cnt);
				cnt++;

				if (arc != NULL)
				{

					//printf("majorfocus %f %f minorfocus %f %f rotateAngle %f c %f\n" , arc->majorFocus.x , arc->majorFocus.y , arc->minorFocus.x , arc->minorFocus.y , arc->rotateAngle , arc->c );
					++nArcNum;				
					std::vector<std::vector<float2> > resPoints = arc->GetSegments(tmpDistance,centers.atHost(i,0),box1,box2);


					if (arc != nextActiveArc)
					{				
						glColor3f(0, 0, 1);
						plot.setRGBColor(0,0,1);
						plot.setLineWidth(lineWidth);
						for (int pos = 0; pos < (int)resPoints.size(); ++pos)
						{
							//printf("what happened??? pos %d size%d\n",pos,resPoints[pos].size());
							glBegin(GL_LINES);
							for (int j = 1; j < (int) resPoints[pos].size(); ++j)
							{
								float2 p1 = make_float2((float)resPoints[pos][j-1].x,(float)resPoints[pos][j-1].y);
								float2 p2 = make_float2((float)resPoints[pos][j].x,(float)resPoints[pos][j].y);
								//printf("p1 %f %f p2 %f %f\n" , p1.x , p1.y , p2.x , p2.y );

								if(!displayOutsideFlag){
									if(getIntersectDisplay(p1,p2,box1,box2)){
										glVertex2f(p1.x,p1.y);
										glVertex2f(p2.x,p2.y);
										plot.drawLineAndChange(p1,p2);
									}
								}else{
									glVertex2f(p1.x,p1.y);
									glVertex2f(p2.x,p2.y);
									plot.drawLineAndChange(p1,p2);
								}
							}
							glEnd();
						}
					}
					else
					{
						//glColor3f(1, 0, 0);
						//glLineWidth(2.5);
					}



					if (arc->leftActiveEdge == NULL)
						arc = NULL;
					else
						arc = arc->leftActiveEdge->leftArc;
				}
			}
			while (arc != NULL && arc != headArc);
		}
		

	}

	//for(int i = 0; i <h_sitesLength[0];++i){
	//	if((h_sites[i].x-h_center[0].x)*(h_sites[i].x-h_center[0].x)+(h_sites[i].y-h_center[0].y)*(h_sites[i].y-h_center[0].y)<distance*distance){
	//		glColor3f(0.5f,0.f,0.5f);
	//	}else{
	//		glColor3f(0.7f,0.7f,0.5f);
	//	}
	//	glVertex2d((float)h_sites[i].x,(float)h_sites[i].y);
	//	//printf("%f %f\n",sites[i].x ,sites[i].y);
	//}



	glPopAttrib();
}



void init(int argc,char** argv)
{
      glClearColor(0.0, 0.0, 0.0, 0.0);
	  glClearDepth(10000.0);
	  glEnable(GL_LINE_SMOOTH);
	  glEnable(GL_POINT_SMOOTH);   
	  glEnable(GL_BLEND);
	  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points   
	  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

	  initCUDA(argc,argv);
}

void clean()
{
	sites.unalloc();
	bounds.unalloc();
	iterateTimes.unalloc();
	vertices.unalloc();
	edges.unalloc();
	arcs.unalloc();
	arcsNoPt.unalloc();
	centers.unalloc();
	distances.unalloc();
	headArcsPos.unalloc();
	activeEdges.unalloc();
	activeEdgesNoPt.unalloc();
	eventHeaps.unalloc();
	arcHeaps.unalloc();

	cutilDeviceReset();
}

void keyboardFunc(unsigned char key,int x , int y)
{
	switch(key){
	case 'o':
		displayOutsideFlag = !displayOutsideFlag;
		break;
	case 27:
		clean();
		exit(0);
		break;
	}

}

 int main(int argc, char** argv)
 {
      /*initialize mode and open window in upper-left corner of
      screen*/
      /*window title is name of program (arg[0])*/
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
        glutInitWindowSize(500, 500);
        glutInitWindowPosition(300, 300);
        glutCreateWindow("sweepcircle");
        glutDisplayFunc(display);
		glutIdleFunc(display);
		glutKeyboardFunc(keyboardFunc);
	    glutReshapeFunc(ReSize);
        init(argc,argv);


		
		printf("event %d\n" , sizeof(Event) );
		printf("ellipse %d\n" , sizeof(struct Ellipse) );
		printf("EllipseArc %d\n" , sizeof( EllipseArc ) );
		printf("ActiveEdge %d\n" , sizeof(ActiveEdge));
		printf("arcHeapEle %d\n" , sizeof(ArcHeapEle));

		printf("align ***********\n");
		printf("event %d\n" , __alignof(Event) );
		printf("ellipse %d\n" , __alignof(struct Ellipse) );
		printf("EllipseArc %d\n" , __alignof( EllipseArc ) );
		printf("ActiveEdge %d\n" , __alignof(ActiveEdge));
		printf("arcHeapEle %d\n" , __alignof(ArcHeapEle));

		/*event 16
			ellipse 8
			EllipseArc 8
			ActiveEdge 8
			arcHeapEle 8*/
		system("del pic\*");

#ifdef _SCANF_
		char ch[100];
		printf("need graphics?");
		scanf("%s" , &ch);
		if( ch[0] == 'n' || ch[0] == 'N' ) return 0;
		glutMainLoop();
#else
	#ifdef _COMMAND_LINE_
		if( argc < argcNum ){
			printf("too few argument\n");
			exit(1);
		}
		if( argv[7][0] == 'n' || argv[7][0] == 'N' ) return 0;
		glutMainLoop();
	#else
		glutMainLoop();
	#endif
#endif
		return 0;
		
}